home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 32 / Amiga Format AFCD32 (Nov 1998, Issue 117).iso / -seriously_amiga- / programming / c / mesa-2.6 / src / amigamesartl.c next >
C/C++ Source or Header  |  1998-08-10  |  31KB  |  1,219 lines

  1.  
  2. /*
  3.  * Mesa 3-D graphics library
  4.  * Version:  2.3
  5.  * Copyright (C) 1995-1997  Brian Paul
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Library General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Library General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Library General Public
  18.  * License along with this library; if not, write to the Free
  19.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22.  
  23. /*
  24.  * amigamesartl.c
  25.  *
  26.  * Version 1.0  27 Jun 1998
  27.  * by Jarno van der Linden
  28.  * jarno@kcbbs.gen.nz
  29.  *
  30.  * Based on ddsample.c ver 1.5
  31.  *
  32.  * Version 1.1  02 Aug 1998
  33.  * by Jarno van der Linden
  34.  * jarno@kcbbs.gen.nz
  35.  *
  36.  * - Fixed several bugs in glClear()
  37.  * - QUICKLOOP macros added
  38.  * - Noticed that { *x = p; x++; } is faster than { *x++ = p; }
  39.  * - Quantizer changed to plugin library
  40.  * - Use environment variables to select quantizer
  41.  *
  42.  */
  43.  
  44.  
  45. /*
  46.  * This is a sample template for writing new Mesa device drivers.
  47.  * You'll have to rewrite all the pseudo code below.
  48.  *
  49.  * Let's say you're interfacing Mesa to a window/operating system
  50.  * called FOO.  Replace all occurances of FOOMesa with the real name
  51.  * you select for your interface  (i.e. XMesa, WMesa, AmigaMesa).
  52.  *
  53.  * You'll have to design an API for clients to use, defined in a
  54.  * header called Mesa/include/GL/FooMesa.h  Use the sample as an
  55.  * example.  The API should at least have functions for creating
  56.  * rendering contexts, binding rendering contexts to windows/frame
  57.  * buffers, etc.
  58.  *
  59.  * Next, you'll have to write implementations for the device driver
  60.  * functions described in dd.h
  61.  *
  62.  * Note that you'll usually have to flip Y coordinates since Mesa's
  63.  * window coordinates start at the bottom and increase upward.  Most
  64.  * window system's Y-axis increases downward
  65.  *
  66.  * Functions marked OPTIONAL may be completely omitted by your driver.
  67.  *
  68.  * Your Makefile should compile this module along with the rest of
  69.  * the core Mesa library.
  70.  */
  71.  
  72.  
  73. #include <stdlib.h>
  74. #include "GL/amigamesartl.h"
  75. #include "context.h"
  76. #include "depth.h"
  77. #include "macros.h"
  78. #include "matrix.h"
  79. #include "types.h"
  80. #include "vb.h"
  81.  
  82. #include "gl/quantizer.h"
  83.  
  84. #include <intuition/intuition.h>
  85. #include <proto/intuition.h>
  86. #include <proto/graphics.h>
  87. #include <proto/utility.h>
  88. #include <proto/exec.h>
  89. #include <proto/dos.h>
  90.  
  91. #include <m68881.h>
  92.  
  93. #define RGBA(r,g,b,a)    (((r)<<24) | ((g)<<16) | ((b)<<8) | (a))
  94.  
  95. #define WINWIDTH(w)        ((w)->Width - (w)->BorderLeft - (w)->BorderRight)
  96. #define WINHEIGHT(w)    ((w)->Height - (w)->BorderTop - (w)->BorderBottom)
  97.  
  98.  
  99. #define QUICKLOOP16(n,l)    { register int ql_var; \
  100.                                 for(ql_var=0; ql_var<((n) & 15); ql_var++) \
  101.                                 { l; }\
  102.                                 for(; ql_var<(n); ql_var+=16) \
  103.                                 { l; l; l; l; l; l; l; l; l; l; l; l; l; l; l; l; } \
  104.                             }
  105.  
  106. #define QUICKLOOP8(n,l)        { register int ql_var; \
  107.                                 for(ql_var=0; ql_var<((n) & 7); ql_var++) \
  108.                                 { l; }\
  109.                                 for(; ql_var<(n); ql_var+=8) \
  110.                                 { l; l; l; l; l; l; l; l; } \
  111.                             }
  112.  
  113. #define QUICKLOOP4(n,l)        { register int ql_var; \
  114.                                 for(ql_var=0; ql_var<((n) & 3); ql_var++) \
  115.                                 { l; }\
  116.                                 for(; ql_var<(n); ql_var+=4) \
  117.                                 { l; l; l; l; } \
  118.                             }
  119.  
  120. #define QUICKLOOP2(n,l)        { register int ql_var; \
  121.                                 for(ql_var=0; ql_var<((n) & 1); ql_var++) \
  122.                                 { l; }\
  123.                                 for(; ql_var<(n); ql_var+=2) \
  124.                                 { l; l; } \
  125.                             }
  126.  
  127. #define QUICKLOOP1(n,l)        { register int ql_var; \
  128.                                 for(ql_var=0; ql_var<(n); ql_var++) \
  129.                                 { l; } \
  130.                             }
  131.  
  132.  
  133. /*
  134.  * This struct contains all device-driver state information.  Think of it
  135.  * as an extension of the core GLcontext from types.h.
  136.  */
  137. struct amiga_mesa_rtl_context {
  138.     GLcontext *gl_ctx;        /* the core library context */
  139.     GLvisual *gl_visual;
  140.     GLframebuffer *gl_buffer;    /* The depth, stencil, accum, etc buffers */
  141.     GLboolean rgb_flag;            /* RGB mode? */
  142.     struct Window *the_window;    /* Window pointer */
  143.     struct DrawInfo *di;        /* DrawInfo pointer for screen info */
  144.     unsigned long *buffer;        /* The image buffer */
  145.     GLint width, height;        /* Size of image buffer */
  146.     GLint wwidth, wheight;        /* Window width and height */
  147.     unsigned long pixel;        /* current color index or RGBA pixel value */
  148.     unsigned long clearpixel;    /* pixel for clearing the color buffers */
  149.     unsigned long numcolours;    /* Number of colours to use for this context */
  150.     unsigned long colourbase;    /* First colour table index */
  151.     struct Library *quantizer;    /* Quantizer library */
  152.     char qname[48];                /* Name of quantizer */
  153.     ULONG qver;                    /* Version of quantizer */
  154.     /* etc... */
  155. };
  156.  
  157.  
  158. static AmigaMesaRTLContext Current = NULL;
  159. static struct Library *quantizerBase = NULL;
  160.  
  161. static const char *renderer_string(void)
  162. {
  163.     return "AmigaMesaRTL";
  164. }
  165.  
  166.  
  167. static void clear_index( GLcontext *ctx, GLuint index )
  168. {
  169.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  170.     /* implement glClearIndex */
  171.     /* usually just save the color index value in the amesartl struct */
  172.     amesartl->clearpixel = amesartl->colourbase + index;
  173. }
  174.  
  175.  
  176. static void clear_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
  177. {
  178.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  179.     /* implement glClearColor */
  180.     /* color components are floats in [0,1] */
  181.     /* usually just save the value in the amesartl struct */
  182.     amesartl->clearpixel = RGBA(r,g,b,a);
  183. }
  184.  
  185.  
  186. static void clear( GLcontext *ctx,
  187.            GLboolean all, GLint x, GLint y, GLint width, GLint height )
  188. {
  189.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  190.     unsigned long *bp;
  191.     unsigned char *bbp;
  192.     unsigned long p;
  193. /*
  194.  * Clear the specified region of the current color buffer using the clear
  195.  * color or index as specified by one of the two functions above.
  196.  * If all==GL_TRUE, clear whole buffer, else just clear region defined
  197.  * by x,y,width,height
  198.  */
  199.  
  200.      p = amesartl->clearpixel;
  201.      y = amesartl->wheight-1-y;
  202.  
  203.     if(amesartl->rgb_flag)
  204.     {
  205.         if(all)
  206.         {
  207.             bp = amesartl->buffer;
  208.             QUICKLOOP16(amesartl->width*amesartl->height,
  209.                 {
  210.                     *bp = p;
  211.                     bp++;
  212.                 }
  213.             )
  214.         }
  215.         else
  216.         {
  217.             bp = amesartl->buffer+y*amesartl->width+x;
  218.             QUICKLOOP16(height,
  219.                 {
  220.                     QUICKLOOP16(width,
  221.                         {
  222.                             *bp = p;
  223.                             bp++;
  224.                         }
  225.                     )
  226.                     bp -= amesartl->width + width;
  227.                 }
  228.             )
  229.         }
  230.     }
  231.     else
  232.     {
  233.         if(all)
  234.         {
  235.             memset(amesartl->buffer, p, amesartl->width * amesartl->height);
  236.         }
  237.         else
  238.         {
  239.             bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
  240.             QUICKLOOP16(height,
  241.                 {
  242.                     memset(bbp, p, width);
  243.                     bbp -= amesartl->width;
  244.                 }
  245.             )
  246.         }
  247.     }
  248. }
  249.  
  250.  
  251. static void set_index( GLcontext *ctx, GLuint index )
  252. {
  253.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  254.     /* Set the current color index. */
  255.     amesartl->pixel = amesartl->colourbase + index;
  256. }
  257.  
  258.  
  259. static void set_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
  260. {
  261.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  262.     /* Set the current RGBA color. */
  263.     /* r is in [0,ctx->Visual->RedScale]   */
  264.     /* g is in [0,ctx->Visual->GreenScale] */
  265.     /* b is in [0,ctx->Visual->BlueScale]  */
  266.     /* a is in [0,ctx->Visual->AlphaScale] */
  267.     amesartl->pixel = RGBA(r,g,b,a);
  268. }
  269.  
  270.  
  271. static GLboolean set_buffer( GLcontext *ctx, GLenum mode )
  272. {
  273.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  274.     /* set the current drawing/reading buffer, return GL_TRUE or GL_FALSE */
  275.     /* for success/failure */
  276.     if (mode==GL_FRONT)
  277.     {
  278.          return GL_TRUE;
  279.     }
  280.     else
  281.     {
  282.         return GL_FALSE;
  283.     }
  284. }
  285.  
  286.  
  287. static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
  288. {
  289.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  290.     /* return the width and height of the current buffer */
  291.     /* if anything special has to been done when the buffer/window is */
  292.     /* resized, do it now */
  293.     GLuint rw,rh;
  294.  
  295.     *width = amesartl->wwidth = WINWIDTH(amesartl->the_window);
  296.     *height = amesartl->wheight = WINHEIGHT(amesartl->the_window);
  297.  
  298.     rw = (((amesartl->wwidth + 15)>>4)<<4);
  299.     rh = amesartl->wheight;
  300.  
  301.     if((rw != amesartl->width) || (rh != amesartl->height))
  302.     {
  303.         if(amesartl->buffer) free(amesartl->buffer);
  304.         amesartl->buffer = NULL;
  305.  
  306.         amesartl->width = rw;
  307.         amesartl->height = rh;
  308.  
  309.         amesartl->buffer = calloc(amesartl->width * amesartl->height, amesartl->rgb_flag ? sizeof(unsigned long) : sizeof(unsigned char));
  310.  
  311.         quantizerBase = amesartl->quantizer;
  312.         ResizeQuantizer(amesartl->width,amesartl->height);
  313.     }
  314. }
  315.  
  316.  
  317. static void write_color_span( GLcontext *ctx,
  318.                               GLuint n, GLint x, GLint y,
  319.                               const GLubyte red[], const GLubyte green[],
  320.                               const GLubyte blue[], const GLubyte alpha[],
  321.                               const GLubyte mask[] )
  322. {
  323.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  324.     unsigned long *bp;
  325.     const GLubyte *ri,*gi,*bi,*ai,*mi;
  326.  
  327.     y = amesartl->wheight-1-y;
  328.     bp = amesartl->buffer+y*amesartl->width+x;
  329.     ri = red;
  330.     gi = green;
  331.     bi = blue;
  332.     ai = alpha;
  333.     mi = mask;
  334.  
  335.     if (mask)
  336.     {
  337.         QUICKLOOP1(n,
  338.             {
  339.                 if (*mi)
  340.                     *bp = RGBA(*ri,*gi,*bi,*ai);
  341.                 mi++;
  342.                 bp++;
  343.                 ri++;
  344.                 gi++;
  345.                 bi++;
  346.                 ai++;
  347.             }
  348.         )
  349.     }
  350.     else
  351.     {
  352.         QUICKLOOP1(n,
  353.             {
  354.                 *bp = RGBA(*ri,*gi,*bi,*ai);
  355.                 bp++;
  356.                 ri++;
  357.                 gi++;
  358.                 bi++;
  359.                 ai++;
  360.             }
  361.         )
  362.     }
  363. }
  364.  
  365.  
  366. static void write_monocolor_span( GLcontext *ctx,
  367.                                   GLuint n, GLint x, GLint y,
  368.                                   const GLubyte mask[])
  369. {
  370.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  371.     unsigned long *bp;
  372.     const GLubyte *mi;
  373.     unsigned long p;
  374.  
  375.     y = amesartl->wheight-1-y;
  376.     bp = amesartl->buffer+y*amesartl->width+x;
  377.     mi = mask;
  378.     p = amesartl->pixel;
  379.  
  380.     QUICKLOOP1(n,
  381.         {
  382.             if (*mi)
  383.                 *bp = p;
  384.             mi++;
  385.             bp++;
  386.         }
  387.     )
  388. }
  389.  
  390.  
  391. static void write_color_pixels( GLcontext *ctx,
  392.                                 GLuint n, const GLint x[], const GLint y[],
  393.                                 const GLubyte r[], const GLubyte g[],
  394.                                 const GLubyte b[], const GLubyte a[],
  395.                                 const GLubyte mask[] )
  396. {
  397.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  398.     const GLubyte *ri,*gi,*bi,*ai,*mi;
  399.     const GLint *xi,*yi;
  400.  
  401.     ri = r;
  402.     gi = g;
  403.     bi = b;
  404.     ai = a;
  405.     mi = mask;
  406.     xi = x;
  407.     yi = y;
  408.  
  409.     QUICKLOOP1(n,
  410.         {
  411.             if (*mi)
  412.                 *(amesartl->buffer + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = RGBA(*ri,*gi,*bi,*ai);
  413.             mi++;
  414.             ri++;
  415.             gi++;
  416.             bi++;
  417.             ai++;
  418.             xi++;
  419.             yi++;
  420.         }
  421.     )
  422. }
  423.  
  424.  
  425. static void write_monocolor_pixels( GLcontext *ctx,
  426.                                     GLuint n,
  427.                                     const GLint x[], const GLint y[],
  428.                                     const GLubyte mask[] )
  429. {
  430.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  431.     const GLubyte *mi;
  432.     const GLint *xi,*yi;
  433.     unsigned long p;
  434.  
  435.     mi = mask;
  436.     xi = x;
  437.     yi = y;
  438.     p = amesartl->pixel;
  439.  
  440.     QUICKLOOP1(n,
  441.         {
  442.             if (*mi)
  443.                 *(amesartl->buffer + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = p;
  444.             mi++;
  445.             xi++;
  446.             yi++;
  447.         }
  448.     )
  449. }
  450.  
  451.  
  452. static void write_index_span( GLcontext *ctx,
  453.                               GLuint n, GLint x, GLint y,
  454.                               const GLuint index[],
  455.                               const GLubyte mask[] )
  456. {
  457.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  458.     unsigned char *bbp;
  459.     const GLuint *ii;
  460.     const GLubyte *mi;
  461.     const unsigned long base = amesartl->colourbase;
  462.  
  463.     y = amesartl->wheight-1-y;
  464.     bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
  465.     ii = index;
  466.     mi = mask;
  467.  
  468.     QUICKLOOP1(n,
  469.         {
  470.             if (*mi)
  471.                 *bbp = *ii + base;
  472.             mi++;
  473.             bbp++;
  474.             ii++;
  475.         }
  476.     )
  477. }
  478.  
  479.  
  480. static void write_monoindex_span( GLcontext *ctx,
  481.                                   GLuint n,GLint x,GLint y,const GLubyte mask[] )
  482. {
  483.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  484.     unsigned char *bbp;
  485.     unsigned long p;
  486.     const GLubyte *mi;
  487.  
  488.     y = amesartl->wheight-1-y;
  489.     bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
  490.     mi = mask;
  491.     p = amesartl->pixel;
  492.  
  493.     QUICKLOOP1(n,
  494.         {
  495.             if (*mi)
  496.                 *bbp = p;
  497.             mi++;
  498.             bbp++;
  499.         }
  500.     )
  501. }
  502.  
  503.  
  504. static void write_index_pixels( GLcontext *ctx,
  505.                                 GLuint n, const GLint x[], const GLint y[],
  506.                                 const GLuint index[], const GLubyte mask[] )
  507. {
  508.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  509.     const GLuint *ii;
  510.     const GLubyte *mi;
  511.     const GLint *xi,*yi;
  512.     const unsigned long base = amesartl->colourbase;
  513.  
  514.     ii = index;
  515.     mi = mask;
  516.     xi = x;
  517.     yi = y;
  518.  
  519.     QUICKLOOP1(n,
  520.         {
  521.             if (*mi)
  522.                 *(((unsigned char *)amesartl->buffer) + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = *ii + base;
  523.             mi++;
  524.             ii++;
  525.             xi++;
  526.             yi++;
  527.         }
  528.     )
  529. }
  530.  
  531.  
  532. static void write_monoindex_pixels( GLcontext *ctx,
  533.                                     GLuint n,
  534.                                     const GLint x[], const GLint y[],
  535.                                     const GLubyte mask[] )
  536. {
  537.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  538.     unsigned long p;
  539.     const GLubyte *mi;
  540.     const GLint *xi,*yi;
  541.  
  542.     p = amesartl->pixel;
  543.     mi = mask;
  544.     xi = x;
  545.     yi = y;
  546.  
  547.     QUICKLOOP1(n,
  548.         {
  549.             if (*mi)
  550.                 *(((unsigned char *)amesartl->buffer) + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = p;
  551.             mi++;
  552.             xi++;
  553.             yi++;
  554.         }
  555.     )
  556. }
  557.  
  558.  
  559. static void read_index_span( GLcontext *ctx,
  560.                              GLuint n, GLint x, GLint y, GLuint index[])
  561. {
  562.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  563.     const unsigned char *bbp;
  564.     GLuint *ii;
  565.     const unsigned long base = amesartl->colourbase;
  566.  
  567.     y = amesartl->wheight-1-y;
  568.     bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
  569.     ii = index;
  570.  
  571.     QUICKLOOP1(n,
  572.         {
  573.             *ii = *bbp - base;
  574.             ii++;
  575.             bbp++;
  576.         }
  577.     )
  578. }
  579.  
  580.  
  581. static void read_color_span( GLcontext *ctx,
  582.                              GLuint n, GLint x, GLint y,
  583.                              GLubyte red[], GLubyte green[],
  584.                              GLubyte blue[], GLubyte alpha[] )
  585. {
  586.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  587.     const unsigned char *bbp;
  588.     GLubyte *ri,*gi,*bi,*ai;
  589.  
  590.     y = amesartl->wheight-1-y;
  591.     bbp = (unsigned char *)(amesartl->buffer+y*amesartl->width+x);
  592.     ri = red;
  593.     gi = green;
  594.     bi = blue;
  595.     ai = alpha;
  596.  
  597.     QUICKLOOP1(n,
  598.         {
  599.             *ri = *bbp;
  600.             ri++;
  601.             bbp++;
  602.             *gi = *bbp;
  603.             gi++;
  604.             bbp++;
  605.             *bi = *bbp;
  606.             bi++;
  607.             bbp++;
  608.             *ai = *bbp;
  609.             ai++;
  610.             bbp++;
  611.         }
  612.     )
  613. }
  614.  
  615.  
  616. static void read_index_pixels( GLcontext *ctx,
  617.                                GLuint n, const GLint x[], const GLint y[],
  618.                                GLuint indx[], const GLubyte mask[] )
  619. {
  620.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  621.     const GLint *xi,*yi;
  622.     GLuint *ii;
  623.     const GLubyte *mi;
  624.     const unsigned long base = amesartl->colourbase;
  625.  
  626.     ii = indx;
  627.     xi = x;
  628.     yi = y;
  629.     mi = mask;
  630.     QUICKLOOP1(n,
  631.         {
  632.             if(*mi)
  633.                 *ii = *(((unsigned char *)amesartl->buffer) + (amesartl->wheight-1-*yi) * amesartl->width + *xi) - base;
  634.             mi++;
  635.             xi++;
  636.             yi++;
  637.             ii++;
  638.         }
  639.     )
  640. }
  641.  
  642.  
  643. static void read_color_pixels( GLcontext *ctx,
  644.                                GLuint n, const GLint x[], const GLint y[],
  645.                                GLubyte red[], GLubyte green[],
  646.                                GLubyte blue[], GLubyte alpha[],
  647.                                const GLubyte mask[] )
  648. {
  649.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  650.     const unsigned char *bbp;
  651.     GLubyte *ri,*gi,*bi,*ai;
  652.     const GLint *xi,*yi;
  653.     const GLubyte *mi;
  654.  
  655.     ri = red;
  656.     gi = green;
  657.     bi = blue;
  658.     ai = alpha;
  659.     xi = x;
  660.     yi = y;
  661.     mi = mask;
  662.  
  663.     QUICKLOOP1(n,
  664.         {
  665.             if(*mi)
  666.             {
  667.                 bbp = (unsigned char *)(amesartl->buffer + (amesartl->wheight-1-*yi) *amesartl->width + *xi);
  668.                 *ri = *bbp;
  669.                 bbp++;
  670.                 *gi = *bbp;
  671.                 bbp++;
  672.                 *bi = *bbp;
  673.                 bbp++;
  674.                 *ai = *bbp;
  675.                 bbp++;
  676.             }
  677.             mi++;
  678.             ri++;
  679.             gi++;
  680.             bi++;
  681.             ai++;
  682.             xi++;
  683.             yi++;
  684.         }
  685.     )
  686. }
  687.  
  688.  
  689.  
  690. static void finish( GLcontext *ctx )
  691. {
  692.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  693.     /* OPTIONAL FUNCTION: implements glFinish if possible */
  694. }
  695.  
  696.  
  697.  
  698. static void flush( GLcontext *ctx )
  699. {
  700.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  701.     /* OPTIONAL FUNCTION: implements glFlush if possible */
  702.  
  703.     /* OK. The big one. Dump the buffer to the window */
  704.  
  705.     /* See if the window is the size we expect it to be. */
  706.     /* If not, better not do anything, we might write into non-existent */
  707.     /* window space. We expect a redraw soon anyway. */
  708.     if((WINWIDTH(amesartl->the_window) != amesartl->wwidth) ||
  709.        (WINHEIGHT(amesartl->the_window) != amesartl->wheight))
  710.         return;
  711.  
  712.     quantizerBase = amesartl->quantizer;
  713.     Quantize(amesartl->buffer);
  714. }
  715.  
  716.  
  717. static GLboolean index_mask( GLcontext *ctx, GLuint mask )
  718. {
  719.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  720.     /* OPTIONAL FUNCTION: implement glIndexMask if possible, else
  721.      * return GL_FALSE
  722.      */
  723.     return(GL_FALSE);
  724. }
  725.  
  726.  
  727. static GLboolean color_mask( GLcontext *ctx,
  728.                              GLboolean rmask, GLboolean gmask,
  729.                              GLboolean bmask, GLboolean amask)
  730. {
  731.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  732.     /* OPTIONAL FUNCTION: implement glColorMask if possible, else
  733.      * return GL_FALSE
  734.      */
  735.     return(GL_FALSE);
  736. }
  737.  
  738.  
  739. static GLboolean logicop( GLcontext *ctx, GLenum op )
  740. {
  741.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  742.     /*
  743.      * OPTIONAL FUNCTION:
  744.      * Implements glLogicOp if possible.  Return GL_TRUE if the device driver
  745.      * can perform the operation, otherwise return GL_FALSE.  If GL_FALSE
  746.      * is returned, the logic op will be done in software by Mesa.
  747.      */
  748.     return(GL_FALSE);
  749. }
  750.  
  751.  
  752. static void dither( GLcontext *ctx, GLboolean enable )
  753. {
  754.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  755.     /* OPTIONAL FUNCTION: enable/disable dithering if applicable */
  756. }
  757.  
  758.  
  759. static void error( GLcontext *ctx )
  760. {
  761.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  762.     /* OPTIONAL FUNCTION: catch error */
  763. }
  764.  
  765.  
  766. /**********************************************************************/
  767. /*****                 Optimized triangle rendering               *****/
  768. /**********************************************************************/
  769. /* (Based on osmesa.c) */
  770.  
  771. /*
  772.  * Smooth-shaded, z triangle, RGBA color.
  773.  */
  774. static void smooth_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  775.                                      GLuint v2, GLuint pv )
  776. {
  777.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  778. #define INTERP_Z 1
  779. #define INTERP_RGB 1
  780. #define INTERP_ALPHA 1
  781. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  782. {                                                                \
  783.    const GLint len = RIGHT-LEFT;                                \
  784.    unsigned long *bp;                                            \
  785.    GLdepth *zr = zRow;                                            \
  786.    GLdepth z;                                                    \
  787.    bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT;    \
  788.    QUICKLOOP1(len,                                                \
  789.       {                                                            \
  790.          z = FixedToDepth(ffz);                                    \
  791.          if (z < *zr) {                                            \
  792.             *zr = z;                                            \
  793.             *bp = RGBA(FixedToInt(ffr), FixedToInt(ffg),        \
  794.                        FixedToInt(ffb), FixedToInt(ffa) );        \
  795.          }                                                        \
  796.          ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;  ffa += fdadx;    \
  797.          ffz += fdzdx;                                            \
  798.          bp++;                                                    \
  799.          zr++;                                                    \
  800.       }                                                            \
  801.    )                                                            \
  802. }
  803. #include "tritemp.h"
  804. }
  805.  
  806.  
  807. /*
  808.  * Flat-shaded, z triangle, RGBA color.
  809.  */
  810. static void flat_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  811.                                    GLuint v2, GLuint pv )
  812. {
  813.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  814. #define INTERP_Z 1
  815. #define SETUP_CODE                    \
  816.    GLubyte r = VB->Color[pv][0];    \
  817.    GLubyte g = VB->Color[pv][1];    \
  818.    GLubyte b = VB->Color[pv][2];    \
  819.    GLubyte a = VB->Color[pv][3];    \
  820.    unsigned long p = RGBA(r,g,b,a);
  821.  
  822. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  823. {                                                                \
  824.    const GLint len = RIGHT-LEFT;                                \
  825.    unsigned long *bp;                                            \
  826.    GLdepth *zr = zRow;                                            \
  827.    GLdepth z;                                                    \
  828.    bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT;    \
  829.    QUICKLOOP1(len,                                                \
  830.       {                                                            \
  831.          z = FixedToDepth(ffz);                                    \
  832.          if (z < *zr) {                                            \
  833.             *zr = z;                                            \
  834.             *bp = p;                                            \
  835.          }                                                        \
  836.          ffz += fdzdx;                                            \
  837.          bp++;                                                    \
  838.          zr++;                                                    \
  839.       }                                                            \
  840.    )                                                            \
  841. }
  842. #include "tritemp.h"
  843. }
  844.  
  845.  
  846.  
  847. /*
  848.  * Smooth-shaded, z-less triangle, RGBA color.
  849.  */
  850. static void smooth_color_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  851.                                    GLuint v2, GLuint pv )
  852. {
  853.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  854. #define INTERP_RGB 1
  855. #define INTERP_ALPHA 1
  856. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  857. {                                                                \
  858.    const GLint len = RIGHT-LEFT;                                \
  859.    unsigned long *bp;                                            \
  860.    bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT;    \
  861.    QUICKLOOP1(len,                                                \
  862.       {                                                            \
  863.          *bp = RGBA(FixedToInt(ffr), FixedToInt(ffg),            \
  864.                     FixedToInt(ffb), FixedToInt(ffa) );            \
  865.          ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;  ffa += fdadx;    \
  866.          bp++;                                                    \
  867.       }                                                            \
  868.    )                                                            \
  869. }
  870. #include "tritemp.h"
  871. }
  872.  
  873.  
  874. /*
  875.  * Flat-shaded, z triangle, RGBA color.
  876.  */
  877. static void flat_color_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  878.                                  GLuint v2, GLuint pv )
  879. {
  880.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  881. #define SETUP_CODE                    \
  882.    GLubyte r = VB->Color[pv][0];    \
  883.    GLubyte g = VB->Color[pv][1];    \
  884.    GLubyte b = VB->Color[pv][2];    \
  885.    GLubyte a = VB->Color[pv][3];    \
  886.    unsigned long p = RGBA(r,g,b,a);
  887.  
  888. #define INNER_LOOP( LEFT, RIGHT, Y )                            \
  889. {                                                                \
  890.    const GLint len = RIGHT-LEFT;                                \
  891.    unsigned long *bp;                                            \
  892.    bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT;    \
  893.    QUICKLOOP1(len,                                                \
  894.       {                                                            \
  895.          *bp = p;                                                \
  896.          bp++;                                                    \
  897.       }                                                            \
  898.    )                                                            \
  899. }
  900. #include "tritemp.h"
  901. }
  902.  
  903.  
  904. /*
  905.  * Return pointer to an accelerated triangle function if possible.
  906.  */
  907. static triangle_func choose_triangle_function( GLcontext *ctx )
  908. {
  909.     struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
  910.  
  911.     if(amesartl->rgb_flag == GL_FALSE)
  912.         return NULL;
  913.  
  914.     if (ctx->Polygon.SmoothFlag)     return NULL;
  915.     if (ctx->Polygon.StippleFlag)    return NULL;
  916.     if (ctx->Texture.Enabled)        return NULL;
  917.  
  918.     if (ctx->RasterMask==DEPTH_BIT
  919.         && ctx->Depth.Func==GL_LESS
  920.         && ctx->Depth.Mask==GL_TRUE)
  921.     {
  922.         if (ctx->Light.ShadeModel==GL_SMOOTH) {
  923.             return smooth_color_z_triangle;
  924.         }
  925.         else
  926.         {
  927.             return flat_color_z_triangle;
  928.         }
  929.     }
  930.     else if(ctx->RasterMask==0)
  931.     {
  932.         if (ctx->Light.ShadeModel==GL_SMOOTH) {
  933.             return smooth_color_triangle;
  934.         }
  935.         else
  936.         {
  937.             return flat_color_triangle;
  938.         }
  939.     }
  940.  
  941.     return NULL;
  942. }
  943.  
  944.  
  945.  
  946. /**********************************************************************/
  947. /**********************************************************************/
  948.  
  949.  
  950. static void setup_DD_pointers( GLcontext *ctx )
  951. {
  952.     /* Initialize all the pointers in the DD struct.  Do this whenever */
  953.     /* a new context is made current or we change buffers via set_buffer! */
  954.  
  955.     ctx->Driver.RendererString = renderer_string;
  956.     ctx->Driver.UpdateState = setup_DD_pointers;
  957.  
  958.     ctx->Driver.ClearIndex = clear_index;
  959.     ctx->Driver.ClearColor = clear_color;
  960.     ctx->Driver.Clear = clear;
  961.  
  962.     ctx->Driver.Index = set_index;
  963.     ctx->Driver.Color = set_color;
  964.  
  965.     ctx->Driver.SetBuffer = set_buffer;
  966.     ctx->Driver.GetBufferSize = get_buffer_size;
  967.  
  968.     /* Pixel/span writing functions: */
  969.     ctx->Driver.WriteColorSpan       = write_color_span;
  970.     ctx->Driver.WriteMonocolorSpan   = write_monocolor_span;
  971.     ctx->Driver.WriteColorPixels     = write_color_pixels;
  972.     ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
  973.     ctx->Driver.WriteIndexSpan       = write_index_span;
  974.     ctx->Driver.WriteMonoindexSpan   = write_monoindex_span;
  975.     ctx->Driver.WriteIndexPixels     = write_index_pixels;
  976.     ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
  977.  
  978.     /* Pixel/span reading functions: */
  979.     ctx->Driver.ReadIndexSpan = read_index_span;
  980.     ctx->Driver.ReadColorSpan = read_color_span;
  981.     ctx->Driver.ReadIndexPixels = read_index_pixels;
  982.     ctx->Driver.ReadColorPixels = read_color_pixels;
  983.  
  984.     ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
  985.  
  986.     /*
  987.      * OPTIONAL FUNCTIONS:  these may be left uninitialized if the device
  988.      * driver can't/needn't implement them.
  989.      */
  990.     ctx->Driver.Flush = flush;
  991. #if 0
  992.     ctx->Driver.Finish = finish;
  993.     ctx->Driver.IndexMask = index_mask;
  994.     ctx->Driver.ColorMask = color_mask;
  995.     ctx->Driver.LogicOp = logicop;
  996.     ctx->Driver.Dither = dither;
  997.     ctx->Driver.Error = error;
  998.     ctx->Driver.NearFar = near_far;
  999. #endif
  1000. }
  1001.  
  1002.  
  1003.  
  1004. /**********************************************************************/
  1005. /*****               FOO/Mesa API Functions                       *****/
  1006. /**********************************************************************/
  1007.  
  1008.  
  1009. __asm __saveds AmigaMesaRTLContext AmigaMesaRTLCreateContextA( register __a0 struct Window *window, register __a1 struct TagItem *tags )
  1010. {
  1011.     AmigaMesaRTLContext c;
  1012.     GLboolean rgb_flag, alpha_flag, db_flag;
  1013.     GLint depth_bits, stencil_bits, accum_bits, index_bits;
  1014.     GLfloat red_scale, green_scale, blue_scale, alpha_scale;
  1015.     GLint red_bits, green_bits, blue_bits, alpha_bits;
  1016.     int maxnumcolours;
  1017.     char *strp,str[32];
  1018.  
  1019.     c = (AmigaMesaRTLContext) calloc( 1, sizeof(struct amiga_mesa_rtl_context) );
  1020.     if (!c)
  1021.     {
  1022.         AmigaMesaRTLDestroyContext( c );
  1023.         return NULL;
  1024.     }
  1025.  
  1026.     rgb_flag = GetTagData(AMRTL_RGBAMode, (ULONG)TRUE, tags) ? GL_TRUE : GL_FALSE;
  1027.     rgb_flag = GetTagData(AMRTL_IndexMode, (ULONG)FALSE, tags) ? GL_FALSE : rgb_flag;
  1028.  
  1029.     if(rgb_flag)
  1030.     {
  1031.         /* RGB(A) mode */
  1032.         alpha_flag = GL_FALSE;
  1033.         db_flag = GL_FALSE;
  1034.         depth_bits = DEPTH_BITS;
  1035.         stencil_bits = STENCIL_BITS;
  1036.         accum_bits = ACCUM_BITS;
  1037.         index_bits = 0;
  1038.         red_scale = 255.0;
  1039.         green_scale = 255.0;
  1040.         blue_scale = 255.0;
  1041.         alpha_scale = 255.0;
  1042.         red_bits = 8;
  1043.         green_bits = 8;
  1044.         blue_bits = 8;
  1045.         alpha_bits = 0;
  1046.     }
  1047.     else
  1048.     {
  1049.         /* color index mode */
  1050.         alpha_flag = GL_FALSE;
  1051.         db_flag = GL_FALSE;
  1052.         depth_bits = DEPTH_BITS;
  1053.         stencil_bits = STENCIL_BITS;
  1054.         accum_bits = ACCUM_BITS;
  1055.         index_bits = 8;
  1056.         red_scale = 0.0;
  1057.         green_scale = 0.0;
  1058.         blue_scale = 0.0;
  1059.         alpha_scale = 0.0;
  1060.         red_bits = 8;
  1061.         green_bits = 8;
  1062.         blue_bits = 8;
  1063.         alpha_bits = 0;
  1064.     }
  1065.  
  1066.     /* Create core visual */
  1067.     c->gl_visual = gl_create_visual( rgb_flag,
  1068.                                      alpha_flag,
  1069.                                      db_flag,
  1070.                                      depth_bits,
  1071.                                      stencil_bits,
  1072.                                      accum_bits,
  1073.                                      index_bits,
  1074.                                      red_scale, green_scale, blue_scale, alpha_scale,
  1075.                                      red_bits, green_bits, blue_bits, alpha_bits );
  1076.  
  1077.     if(!c->gl_visual)
  1078.     {
  1079.         AmigaMesaRTLDestroyContext( c );
  1080.         return NULL;
  1081.     }
  1082.  
  1083.     c->gl_ctx = gl_create_context( c->gl_visual,
  1084.                                    NULL,
  1085.                                    (void *) c );
  1086.  
  1087.     if(!c->gl_ctx)
  1088.     {
  1089.         AmigaMesaRTLDestroyContext( c );
  1090.         return NULL;
  1091.     }
  1092.  
  1093.     c->gl_buffer = gl_create_framebuffer( c->gl_visual );
  1094.     if(!c->gl_buffer)
  1095.     {
  1096.         AmigaMesaRTLDestroyContext( c );
  1097.         return NULL;
  1098.     }
  1099.  
  1100.     c->rgb_flag = rgb_flag;
  1101.     c->the_window = window;
  1102.     c->di = GetScreenDrawInfo(c->the_window->WScreen);
  1103.     if(!c->di)
  1104.     {
  1105.         AmigaMesaRTLDestroyContext( c );
  1106.         return NULL;
  1107.     }
  1108.     c->buffer = NULL;
  1109.     c->width = 0;
  1110.     c->height = 0;
  1111.     c->wwidth = WINWIDTH(c->the_window);
  1112.     c->wheight = WINHEIGHT(c->the_window);
  1113.     c->pixel = 0;
  1114.     c->clearpixel = 0;
  1115.     maxnumcolours = 1L<<c->di->dri_Depth;
  1116.     c->numcolours = GetTagData(AMRTL_NumColours, maxnumcolours, tags);
  1117.     c->colourbase = GetTagData(AMRTL_ColourBase, (ULONG)0, tags);
  1118.     if(c->colourbase > (maxnumcolours-2))
  1119.         c->colourbase = maxnumcolours-2;
  1120.     if(c->colourbase < 0)
  1121.         c->colourbase = 0;
  1122.     if((c->colourbase + c->numcolours) > maxnumcolours)
  1123.     {
  1124.         c->numcolours = maxnumcolours-c->colourbase;
  1125.     }
  1126.     if(c->numcolours < 2)
  1127.         c->numcolours = 2;
  1128.  
  1129.     strcpy(c->qname,"quantizers/");
  1130.     if(GetVar("AmigaMesaRTL/Quantizer",str,32,0) == -1)
  1131.         strcpy(str,"dl1");
  1132.     strp = (char *)GetTagData(AMRTL_Quantizer, NULL, tags);
  1133.     if(strp)
  1134.     {
  1135.         strncpy(str,strp,32);
  1136.         str[31] = '\0';
  1137.     }
  1138.     strcat(c->qname,str);
  1139.  
  1140.     c->qver = 0;
  1141.     if(GetVar("AmigaMesaRTL/QuantizerVersion",str,32,0) != -1)
  1142.         c->qver = atol(str);
  1143.     c->qver = GetTagData(AMRTL_QuantizerVersion, c->qver, tags);
  1144.  
  1145.     c->quantizer = OpenLibrary(c->qname,c->qver);
  1146.     if(!c->quantizer)
  1147.     {
  1148.         AmigaMesaRTLDestroyContext( c );
  1149.         return NULL;
  1150.     }
  1151.  
  1152.     quantizerBase = c->quantizer;
  1153.     if(!InitQuantizer(window, rgb_flag ? AMRTL_RGBAMode : AMRTL_IndexMode, c->numcolours, c->colourbase))
  1154.     {
  1155.         AmigaMesaRTLDestroyContext( c );
  1156.         return NULL;
  1157.     }
  1158.  
  1159.     return c;
  1160. }
  1161.  
  1162.  
  1163.  
  1164. __asm __saveds void AmigaMesaRTLDestroyContext( register __a0 AmigaMesaRTLContext c )
  1165. {
  1166.     if(c)
  1167.     {
  1168.         if(c->quantizer)
  1169.         {
  1170.             quantizerBase = c->quantizer;
  1171.             DeleteQuantizer();
  1172.             CloseLibrary(c->quantizer);
  1173.         }
  1174.  
  1175.         if(c->di) FreeScreenDrawInfo(c->the_window->WScreen, c->di);
  1176.         c->di = NULL;
  1177.  
  1178.         if(c->gl_buffer) gl_destroy_framebuffer( c->gl_buffer );
  1179.         c->gl_buffer = NULL;
  1180.  
  1181.         if(c->gl_ctx) gl_destroy_context( c->gl_ctx );
  1182.         c->gl_ctx = NULL;
  1183.  
  1184.         if(c->gl_visual) gl_destroy_visual( c->gl_visual );
  1185.         c->gl_visual = NULL;
  1186.  
  1187.         if(c->buffer) free(c->buffer);
  1188.         c->buffer = NULL;
  1189.  
  1190.         free(c);
  1191.     }
  1192.     c = NULL;
  1193. }
  1194.  
  1195.  
  1196.  
  1197. /*
  1198.  * Make the specified context the current one
  1199.  * Might also want to specify the window/drawable here, like for GLX.
  1200.  */
  1201. __asm __saveds void AmigaMesaRTLMakeCurrent( register __a0 AmigaMesaRTLContext c )
  1202. {
  1203.     gl_make_current( c->gl_ctx, c->gl_buffer );
  1204.     setup_DD_pointers( c->gl_ctx );
  1205.     gl_Viewport( c->gl_ctx, 0, 0, c->wwidth, c->wheight );
  1206.  
  1207.     Current = c;
  1208. }
  1209.  
  1210.  
  1211. __asm __saveds AmigaMesaRTLContext AmigaMesaRTLGetCurrentContext( void )
  1212. {
  1213.     return Current;
  1214. }
  1215.  
  1216.  
  1217. /* you may need to add other FOO/Mesa functions too... */
  1218.  
  1219.